﻿using Future.Common;
using Future.Common.Const;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using JwtRegisteredClaimNames = Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames;

namespace Future.Web.Utility
{
    /// <summary>
    /// token工具类
    /// </summary>
    public class JwtInvoker
    {
        private readonly JwtTokenOptions _jwtTokenOptions;

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="jwtTokenOptions"></param>
        public JwtInvoker(IOptionsMonitor<JwtTokenOptions> jwtTokenOptions)
        {
            _jwtTokenOptions = jwtTokenOptions.CurrentValue;
        }

        /// <summary>
        /// 获取token
        /// </summary>
        /// <param name="user"></param>
        /// <param name="menus"></param>
        /// <returns></returns>
        public string GetAccessToken(UserModel user, HashSet<MenuModel> menus)
        {
            return GetToken(_jwtTokenOptions.Expiration, user, menus);
        }

        /// <summary>
        /// 生成token
        /// </summary>
        /// <param name="minutes"></param>
        /// <param name="user"></param>
        /// <param name="menus"></param>
        /// <returns></returns>
        private string GetToken(int minutes, UserModel user, HashSet<MenuModel> menus)
        {
            List<Claim> claims = new()
            {
                new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
                new Claim(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(DateTime.Now.AddMinutes(minutes)).ToUnixTimeSeconds()}"),
                new Claim(JwtRegisteredClaimNames.Sid, user.Id.ToString()),
                new Claim(SystemConst.USERNAMECLAIM, user.UserName)
            };
            //claims.Add(new Claim("userModel", user.ToJson()));
            //-----------------------------以下从user的权限表中添加权限-----------------------例如：

            foreach (var m in menus)
            {
                if (!string.IsNullOrEmpty(m.PermissionCode))
                {
                    claims.Add(new Claim(SystemConst.PERMISSIONCLAIM, m.PermissionCode));
                }
            }
            if (SystemConst.ADMIN.Equals(user.UserName))
            {
                claims.Add(new Claim(SystemConst.PERMISSIONCLAIM, SystemConst.ADMINPERMISSIONCODE));
            }

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtTokenOptions.Secret));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
                issuer: _jwtTokenOptions.Issuer,
                audience: _jwtTokenOptions.Audience,
                claims: claims,
                expires: DateTime.Now.AddMinutes(minutes),
                signingCredentials: credentials);
            var tokenData = new JwtSecurityTokenHandler().WriteToken(token);

            return tokenData;
        }
    }
}
